package com.ysq.www.common.utils.message;

import com.alibaba.druid.util.StringUtils;
import com.alibaba.fastjson.JSONObject;
import com.ysq.www.api.user.entity.MessageConfig;
import com.ysq.www.common.config.ApplicationContextUtil;
import com.ysq.www.common.utils.RedisUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.codec.binary.Base64;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.util.EntityUtils;
import org.springframework.stereotype.Component;

import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.security.AlgorithmParameters;
import java.util.HashMap;
import java.util.Map;

@Slf4j
@Component
public class SendMessageUtil {

    /**
     * 发送统一服务消息（公众号模板消息）
     * @param openId 用户openId
     * @param first 模板消息头部
     * @param k1 值1
     * @param k2 值2
     * @param k3 值3
     * @param remark 结尾
     */
    public static void sendMessageByApplet(MessageConfig mc, String openId, String first, String k1, String k2, String k3, String remark){
        try {
            //获取spring容器中的对象
            RedisUtil redisUtil = ApplicationContextUtil.get(RedisUtil.class);
            //先获取access_token
            String accessToken = (String) redisUtil.get("accessToken");
            if (StringUtils.isEmpty(accessToken)){
                log.info("获取小程序全局AccessToken失败!");
                return;
            }
            JSONObject data = new JSONObject();
            Map<String,Object> map1 = new HashMap<>();
            map1.put("value",first);
            map1.put("color","#173177");
            data.put("first",map1);
            Map<String,Object> map2 = new HashMap<>();
            map2.put("value", k1);
            map2.put("color","#173177");
            data.put("keyword1",map2);
            Map<String,Object> map3 = new HashMap<>();
            map3.put("value",k2);
            map3.put("color","#173177");
            data.put("keyword2",map3);
            Map<String,Object> map4 = new HashMap<>();
            map4.put("value", k3);
            map4.put("color","#173177");
            data.put("keyword3",map4);
            Map<String,Object> map5 = new HashMap<>();
            map5.put("value",remark);
            map5.put("color","#173177");
            data.put("remark",map5);

            JSONObject jsonObject = sendAppletMessage(accessToken, openId, mc.getAppId(), mc.getTemplateId(),
                    mc.getUrl(), mc.getAppletId(), mc.getPagePath(), data);
            Integer errCode = jsonObject.getInteger("errcode");
            String errMsg = jsonObject.getString("errmsg");
            if (errCode == 0 && errMsg.equals("ok")){
                log.info("发送消息成功!");
            }else log.info("发送消息失败!失败错误码:"+errCode+"--错误原因:"+errMsg);
        }catch (Exception e){
            e.printStackTrace();
            throw e;
        }
    }

    /**
     * 统一服务消息
     * 公众号模板消息,发送公众号通知
     * @param token  小程序ACCESS_TOKEN
     * @param openId 用户openid，可以是小程序的openid，也可以是公众号的openid
     * @param appId 公众号appId
     * @param templateId 公众号模板消息模板id
     * @param url   公众号模板消息所要跳转的url
     * @param appletId 公众号模板消息所要跳转的小程序appid，小程序的必须与公众号具有绑定关系
     * @param pagePath 公众号模板消息所要跳转的小程序页面
     * @param data 公众号模板消息的数据
     * @return
     */
    private static JSONObject sendAppletMessage(String token, String openId, String appId,
           String templateId, String url, String appletId, String pagePath, JSONObject data) {
        JSONObject result = new JSONObject();
        JSONObject obj = new JSONObject();
        JSONObject mp_template_msg = new JSONObject();
        JSONObject miniprogram = new JSONObject();
        try{
            HttpClient client = HttpClientBuilder.create().build();//构建一个Client
            String path = "https://api.weixin.qq.com/cgi-bin/message/wxopen/template/uniform_send?access_token="+token;
            obj.put("touser",openId);
            mp_template_msg.put("appid",appId);
            mp_template_msg.put("template_id",templateId);
            mp_template_msg.put("url",url);
            miniprogram.put("appid",appletId);
            miniprogram.put("pagepath",pagePath);
            mp_template_msg.put("miniprogram",miniprogram);
            mp_template_msg.put("data",data);
            obj.put("mp_template_msg",mp_template_msg);
            System.out.println(obj.toJSONString());
            System.out.println(obj.toJSONString());
            System.out.println(obj.toJSONString());
            HttpPost httpPost = new HttpPost(url);
            StringEntity entity = new StringEntity(obj.toString(), ContentType.APPLICATION_JSON);
            httpPost.setEntity(entity);//放入json请求参数
            HttpResponse response = client.execute(httpPost);
            String json = EntityUtils.toString(response.getEntity(), "utf-8");
            result = JSONObject.parseObject(json);
        }catch (Exception e){
            e.printStackTrace();
            return null;
        }
        return result;
    }


    /**
     * AES解密
     *
     * @param data      //密文，被加密的数据
     * @param key      //秘钥
     * @param iv       //偏移量
     * @param encodingFormat //解密后的结果需要进行的编码
     * @return
     * @throws Exception
     */
    public static String decrypt(String data, String key, String iv, String encodingFormat) {
        //被加密的数据
        byte[] dataByte = Base64.decodeBase64(data);
        //加密秘钥
        byte[] keyByte = Base64.decodeBase64(key);
        //偏移量
        byte[] ivByte = Base64.decodeBase64(iv);
        try {
            Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");

            SecretKeySpec spec = new SecretKeySpec(keyByte, "AES");

            AlgorithmParameters parameters = AlgorithmParameters.getInstance("AES");
            parameters.init(new IvParameterSpec(ivByte));

            cipher.init(Cipher.DECRYPT_MODE, spec, parameters);// 初始化

            byte[] resultByte = cipher.doFinal(dataByte);
            if (null != resultByte && resultByte.length > 0) {
                String result = new String(resultByte, encodingFormat);
                return result;
            }
            return null;
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

}
